/*
 * $Id: QEADIFElement.m 73 2009-06-19 01:50:56Z jon@bway.net $
 * Chalk
 *
 * Created 6/4/09
 * Copyright Jon Gordon
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import "QEADIFElement.h"

#import "QEADIFInternal.h"

@implementation QEADIFElement

@synthesize line, position, fieldName, typeCode, fieldValue, src, error;


#pragma mark LIFECYCLE METHODS
+ (BOOL)accessInstanceVariablesDirectly
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    return NO;
} // accessInstanceVariablesDirectly

+ (void)initialize
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    static BOOL initialized = NO;
    
    if (!initialized) {
        //-NSLog(@"  initializing");
        initialized = YES;
    } // if
} // initialize

- (void)dealloc
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    [self setFieldName:nil];
    [self setFieldValue:nil];
    [self setSrc:nil];
    [self setError:nil];
    
    [super dealloc];
} // dealloc    


+ (QEADIFElement *)elementTagWithFieldName:(NSString *)newFieldName 
                                fromSource:(NSString *)newSrc 
                                    atLine:(NSUInteger)newLine 
                               andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setFieldName:newFieldName];
    [result setSrc:newSrc];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementTagWithFieldName:fromSource:atLine:andPosition:

+ (QEADIFElement *)elementFieldWithFieldName:(NSString *)newFieldName
                                  fieldValue:(NSString *)newFieldValue
                                  fromSource:(NSString *)newSrc 
                                      atLine:(NSUInteger)newLine 
                                 andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setFieldName:newFieldName];
    [result setFieldValue:newFieldValue];
    [result setTypeCode:qeADIFTypeUndefined];
    [result setSrc:newSrc];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementFieldWithFieldName:fieldValue:fromSource:atLine:andPosition:

+ (QEADIFElement *)elementFieldWithFieldName:(NSString *)newFieldName
                                  fieldValue:(NSString *)newFieldValue
                                      ofType:(unichar)newFieldTypeCode
                                  fromSource:(NSString *)newSrc 
                                      atLine:(NSUInteger)newLine 
                                 andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setFieldName:newFieldName];
    [result setFieldValue:newFieldValue];
    [result setTypeCode:newFieldTypeCode];
    [result setSrc:newSrc];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementFieldWithFieldName:fieldValue:ofType:fromSource:atLine:andPosition:

+ (QEADIFElement *)elementError:(NSError *)newError
                     fromSource:(NSString *)newSrc 
                         atLine:(NSUInteger)newLine 
                    andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setError:newError];
    [result setSrc:newSrc];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementError:fromSource:atLine:andPosition:

+ (QEADIFElement *)elementCommentFromSource:(NSString *)newSrc 
                                     atLine:(NSUInteger)newLine 
                                andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setSrc:newSrc];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementCommentFromSource:atLine:andPosition:

+ (QEADIFElement *)elementEOIAtLine:(NSUInteger)newLine 
                        andPosition:(NSUInteger)newPos
{
    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    QEADIFElement *result = [[[QEADIFElement alloc] init] autorelease];
    [result setSrc:nil];
    [result setLine:newLine];
    [result setPosition:newPos];
    
    return result;
} // elementEOIAtLine:andPosition:

- (BOOL)isError
{
    return nil != [self error];
} // isError

- (BOOL)isEOI
{
    return ![self isError] && (nil == [self src]);
} // isEOI

- (BOOL)isComment
{
    return ![self isError] && ![self isEOI] && (nil == [self fieldName]);
} // isComment

- (BOOL)isTag
{
    return ![self isError] &&
    ![self isEOI] &&
    ![self isComment] &&
    (nil == [self fieldValue]);
} // isTag

- (BOOL)isField
{
    return  ![self isError] &&
    ![self isEOI] &&
    ![self isComment] &&
    (nil != [self fieldValue]);
} // isField

- (QEADIFElementTypeCode)elementType
{
    if ([self isField])
        return qeADIFElementField;
    
    if ([self isTag])
        return qeADIFElementTag;
    
    if ([self isComment])
        return qeADIFElementComment;
    
    if ([self isEOI])
        return qeADIFElementEOI;
    
    NSAssert([self isError],
             @"QEADIFElement must acknowledge being one of the five types.");
    return qeADIFElementError;
} // elementType

- (NSString *)description
{
    //    //-NSLog(@"MESSAGE: %s", __PRETTY_FUNCTION__);
    NSString *result = nil;
    switch ([self elementType]) {
        case qeADIFElementField:
            result = [NSString stringWithFormat:@"field(%lu,%lu)<%@>%@",
                      ((unsigned long) [self line]),
                      ((unsigned long) [self position]),
                      [self fieldName],
                      [self fieldValue]];
            break;
        case qeADIFElementTag:
            result = [NSString stringWithFormat:@"tag(%lu,%lu)<%@>",
                      ((unsigned long) [self line]),
                      ((unsigned long) [self position]),
                      [self fieldName]];
            break;
        case qeADIFElementComment:
            result = [NSString stringWithFormat:@"comment(%lu,%lu):\"%@\"",
                      ((unsigned long) [self line]),
                      ((unsigned long) [self position]),
                      [self src]];
            break;
        case qeADIFElementEOI:
            result = [NSString stringWithFormat:@"[eoi](%lu,%lu)",
                      ((unsigned long) [self line]),
                      ((unsigned long) [self position])];
            break;
        case qeADIFElementError:
            result = [[[self error] userInfo] objectForKey:NSLocalizedDescriptionKey];
            break;
        default:
            NSAssert(NO, // always fails
                     @"CAN'T HAPPEN: description can't figure out element type");
            result = @"--IMPOSSIBLE ELEMENT--";
    } // switch

    return result;
} // description
@end
